#include "steganalyzer.hpp"

#include <boost/math/distributions/chi_squared.hpp>

namespace StegAnalyzer
{

void chiSquaredTest(ui_t pDepth, const vuc_t& pData)
{

    vuc_t bitdata;

    vuc_t::const_iterator dataiter;
    for(dataiter=pData.begin(); dataiter != pData.end(); ++dataiter)
    {
        uc_t bd = 0;
        for(ui_t depth=pDepth; depth>0; --depth)
        {
            uc_t depthshift = 1;
            depthshift = depthshift << (depth-1);
            depthshift = *dataiter&depthshift;
            bd |= depthshift;
        }
        bitdata.push_back(bd);
    }

    ui_t maxval = 1;
    for(ui_t d = 0; d < pDepth; ++d)
    {
        maxval *= 2;
    }

    vui_t freedom;
    for(ui_t d = 0; d < maxval; ++d)
    {
        freedom.push_back(0);
    }
    for(dataiter=bitdata.begin(); dataiter != bitdata.end(); ++dataiter)
    {
        for(ui_t val = 0; val < maxval; ++val)
        {
            if(val == *dataiter)
            {
                ++freedom.at(val);
            }
        }
    }

    ui_t totalpixels = pData.size();
    float expectedvalue = totalpixels / maxval;

    float chiscore = 0;

    for(ui_t i=0; i<maxval; ++i)
    {
        float chi = (float)(freedom.at(i) - expectedvalue);
        chi *= chi;
        chi = chi/expectedvalue;
        chiscore += chi;
        std::cout<<i<<" - observed: "<<freedom.at(i)<<" expected: "<<expectedvalue<<" chi: "<<chi<<std::endl;
    }

    std::cout<<"chi: "<<chiscore<<std::endl;

    boost::math::chi_squared dist(maxval-1);

    float pvalue = boost::math::cdf(dist, chiscore);

    std::cout<<"p-value: "<<pvalue<<std::endl;

}

}
